﻿using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Net8.Project.Common.Extensions;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;

namespace Net8.Project.Common.HttpContextUser
{
    /// <summary>
    /// AspNet 用户上下文实现，提供当前用户信息的获取与相关操作。
    /// </summary>
    public class AspNetUser : IUser
    {
        private readonly IHttpContextAccessor _accessor;
        private readonly ILogger<AspNetUser> _logger;

        /// <summary>
        /// 构造函数，注入HttpContext访问器和日志记录器。
        /// </summary>
        public AspNetUser(IHttpContextAccessor accessor, ILogger<AspNetUser> logger)
        {
            _accessor = accessor;
            _logger = logger;
        }

        /// <summary>
        /// 当前用户名称
        /// </summary>
        public string Name => GetName();

        /// <summary>
        /// 获取当前用户名称
        /// </summary>
        /// <returns>用户名</returns>
        private string GetName()
        {
            if (IsAuthenticated() && !_accessor.HttpContext.User.Identity.Name.IsNullOrEmpty())
            {
                return _accessor.HttpContext.User.Identity.Name;
            }
            return string.Empty;
        }

        /// <summary>
        /// 当前用户ID（从jti Claim获取）
        /// </summary>
        public long ID => GetClaimValueByType("jti").FirstOrDefault().ObjToLong();

        /// <summary>
        /// 当前用户所属租户ID（从TenantId Claim获取）
        /// </summary>
        public long TenantId => GetClaimValueByType("TenantId").FirstOrDefault().ObjToLong();

        /// <summary>
        /// 判断当前用户是否已通过身份验证
        /// </summary>
        /// <returns>已认证返回true，否则返回false</returns>
        public bool IsAuthenticated()
        {
            return _accessor.HttpContext?.User?.Identity?.IsAuthenticated ?? false;
        }

        /// <summary>
        /// 获取当前请求的Token字符串
        /// </summary>
        /// <returns>Token字符串</returns>
        public string GetToken()
        {
            var token = _accessor.HttpContext?.Request?.Headers["Authorization"].ObjToString();
            if (!token.IsNullOrEmpty() && token.StartsWith("Bearer "))
            {
                return token["Bearer ".Length..].Trim();
            }
            return string.Empty;
        }

        /// <summary>
        /// 从Token中获取指定类型的用户信息
        /// </summary>
        /// <param name="claimType">声明类型</param>
        /// <returns>用户信息列表</returns>
        public List<string> GetUserInfoFromToken(string claimType)
        {
            var token = GetToken();
            var jwtHandler = new JwtSecurityTokenHandler();
            if (!token.IsNullOrEmpty() && jwtHandler.CanReadToken(token))
            {
                var jwtToken = jwtHandler.ReadJwtToken(token);
                return jwtToken.Claims
                    .Where(item => item.Type == claimType)
                    .Select(item => item.Value)
                    .ToList();
            }
            return new List<string>();
        }

        /// <summary>
        /// 获取当前用户的所有声明（Claims）
        /// </summary>
        /// <returns>声明集合</returns>
        public IEnumerable<Claim> GetClaimsIdentity()
        {
            if (_accessor.HttpContext == null)
                return Array.Empty<Claim>();

            if (!IsAuthenticated())
                return GetClaimsIdentity(GetToken());

            var claims = _accessor.HttpContext.User.Claims.ToList();
            // 可选：将请求头作为Claim添加（如无特殊需求可移除）
            foreach (var header in _accessor.HttpContext.Request.Headers)
            {
                claims.Add(new Claim(header.Key, header.Value));
            }
            return claims;
        }

        /// <summary>
        /// 根据Token获取声明集合
        /// </summary>
        /// <param name="token">JWT Token</param>
        /// <returns>声明集合</returns>
        public IEnumerable<Claim> GetClaimsIdentity(string token)
        {
            var jwtHandler = new JwtSecurityTokenHandler();
            if (!token.IsNullOrEmpty() && jwtHandler.CanReadToken(token))
            {
                var jwtToken = jwtHandler.ReadJwtToken(token);
                return jwtToken.Claims;
            }
            return Array.Empty<Claim>();
        }

        /// <summary>
        /// 根据声明类型获取当前用户的声明值列表
        /// </summary>
        /// <param name="claimType">声明类型</param>
        /// <returns>声明值列表</returns>
        public List<string> GetClaimValueByType(string claimType)
        {
            return GetClaimsIdentity()
                .Where(item => item.Type == claimType)
                .Select(item => item.Value)
                .ToList();
        }
    }
}
